package service

import (
	"duoke/internal/dao"
	"duoke/model"
	"duoke/tables"
	"duoke/utils/gconv"
	"duoke/utils/orm"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gogf/gf/v2/os/gtime"
	gconv2 "github.com/gogf/gf/v2/util/gconv"
)

var Group = new(groupService)

type groupService struct{}

func (s *groupService) List(c *gin.Context, where string, limit int, field string) ([]model.Order, error) {
	accountR, _ := Request.Account(c)
	order := make([]model.Order, 0)
	var req model.ReqList
	//判断子账户
	query := orm.Db.Desc("id").Cols(field).Limit(limit).Where("is_head =1 AND pay_state = 1").Where(where)
	if accountR.Role == "goods" {
		query = query.Where("goods_id IN(?)", accountR.GoodsIds)
	} else {
		query = query.Where("acid =?", accountR.Id)
	}
	err := query.Find(&order)
	if err != nil {
		return nil, err
	}
	for index, item := range order {
		if item.GroupId > 0 {
			member, err := s.Member(req, item.GroupId, false, "")
			if err != nil {
				return nil, err
			}
			order[index].Member = member
		}
	}
	return order, nil
}
func (s *groupService) Page(c *gin.Context, req model.ReqList, where string, field string) ([]model.Order, int64, error) {
	accountR, _ := Request.Account(c)
	// 分页
	offset := (req.PageNo - 1) * req.PageSize
	list := make([]model.Order, 0)
	//判断子账户
	query := orm.Db.Desc("id").Cols(field).Limit(req.PageSize, offset).Where(where)
	if accountR.Role == "goods" {
		query = query.Where("goods_id IN(?)", accountR.GoodsIds)
	} else {
		query = query.Where("acid =?", accountR.Id)
	}
	total, err := query.FindAndCount(&list)
	if err != nil {
		return nil, 0, err
	}
	for index, item := range list {
		if item.GroupId > 0 {
			req.IsRobot = ""
			member, err := s.Member(req, item.GroupId, false, "")
			if err != nil {
				return nil, 0, err
			}
			list[index].Member = member
		}
	}
	return list, total, nil
}
func (s *groupService) Info(c *gin.Context, groupId int) (*model.Order, error) {
	goodsR, _ := Request.Goods(c)
	goodsUserR, _ := Request.GoodsUser(c)
	group := new(model.Order)
	has, err := orm.Db.ID(groupId).Where("goods_id =? AND pay_state = ? AND is_head = 1", goodsR.Id, 1).Get(group)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, errors.New("团不存在")
	}
	group.HasBuy, err = orm.Db.Where("goods_id =? AND user_id =? AND group_id =? AND pay_state =1", goodsR.Id, goodsUserR.UserId, group.Id).Count(new(model.Order))
	if err != nil {
		return nil, err
	}
	return group, nil
}
func (s *groupService) Member(req model.ReqList, groupId int, isAll bool, field string) ([]model.Order, error) {
	member := make([]model.Order, 0)
	if req.IsRobot != "" {
		err := orm.Db.Desc("is_head").Where("group_id = ? AND pay_state = 1 AND is_robot =?", groupId, req.IsRobot).
			Cols(field).
			Find(&member)
		if err != nil {
			return nil, err
		}
	} else {
		err := orm.Db.Desc("is_head").Where("group_id = ? AND pay_state = 1", groupId).
			Cols(field).
			Find(&member)
		if err != nil {
			return nil, err
		}
	}
	if isAll {
		return member, nil
	} else {
		return member[1:], nil
	}
}
func (s *groupService) InfoById(id int, field string) (*tables.SeparateGroup, error) {
	user := new(tables.SeparateGroup)
	has, err := orm.Db.ID(id).Cols(field).Get(user)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, errors.New("地址信息不存在")
	}
	return user, nil
}

func (s *groupService) RankingVersion(c *gin.Context, req *model.ReqListV2) (*[]tables.GroupOpen, int64, error) {
	var m []tables.GroupOpen
	// 执行查询操作
	offset := (req.PageNo - 1) * req.PageSize
	var where string
	if req.FromId != 0 {
		where = fmt.Sprintf("goods_id=%d", req.FromId)
	}
	count, err := orm.Db.OrderBy("weight desc,id asc").Where(where).Limit(req.PageSize, offset).
		FindAndCount(&m)
	return &m, count, err
}

// Withdrawal 申请提现
func (s *groupService) Withdrawal(c *gin.Context, req *model.ReqWithdrawal) error {
	// 判断用户所拥有金额
	user, err := User.Info(c, "*")
	if err != nil {
		return errors.New("用户信息不存在")
	}
	if gconv.Float32(user.UserMoney) < req.Money {
		return errors.New("可提现最大金额：" + gconv.String(user.Money) + "元")
	}
	// 开启事务处理
	session := orm.Db.NewSession()
	defer session.Close()
	if err = session.Begin(); err != nil {
		return errors.New("启动事务失败")
	}
	// 获取提现手续费
	otherSetting, err := AccountSetting.Info(c, "other")
	if err != nil {
		return errors.New("获取参数配置错误")
	}
	cashFeeRate := otherSetting["cash_fee_rate"]
	m := model.ReqWithdrawal{
		Money:    req.Money,
		Feel:     gconv.Float32(cashFeeRate),
		UserId:   user.Id,
		State:    2,
		SubMchId: user.SubMchId,
	}
	m.FreezeAmount = (1 - m.Feel) * m.Money
	insert, err := session.Table("withdrawal").InsertOne(m)
	if err != nil && insert == 0 {
		session.Rollback()
		return errors.New("添加失败")
	}
	// 添加完成后扣除用户的佣金
	err = User.UserMoney(c, user.Id, -gconv.Float64(req.Money), "提现", "")
	if err != nil {
		session.Rollback()
		return errors.New("扣款失败：" + err.Error())
	}
	// 提交事务
	if err = session.Commit(); err != nil {
		return errors.New("事务提交失败")
	}
	return nil
}

// GiveIntegral 团员团长赠送积分
func (s *groupService) GiveIntegral(c *gin.Context, req map[string]any) error {
	memberPoints := gconv.Int(req["member_points"])
	groupPoints := gconv.Int(req["group_points"])
	if memberPoints == groupPoints && memberPoints == 0 {
		return errors.New("没有设定团员和团长的积分奖励")
	}
	headOrder := new(model.Order)
	gconv2.Struct(req["headOrder"], headOrder)
	// 获取团员id
	var o []model.Order
	err := dao.Order.Ctx(c).Where("group_id = ? and is_head = 0", headOrder.Id).Scan(&o)
	if err != nil {
		return err
	}
	var userId []int
	for _, item := range o {
		userId = append(userId, item.UserId)
	}
	session := orm.Db.NewSession()
	defer session.Close()
	if err = session.Begin(); err != nil {
		return err
	}

	// 赠送积分
	// 1 团员积分
	var socre []tables.UserScoreLog
	if memberPoints > 0 {
		_, err = session.In("id", userId).
			Incr("score", memberPoints).
			Update(&tables.User{})
		if err != nil {
			session.Rollback()
			return err
		}
		for _, item := range userId {
			socre = append(socre, tables.UserScoreLog{
				Type:      "default",
				UserId:    item,
				Score:     memberPoints,
				Remark:    "团员赠送积分",
				CreatedAt: gconv.Int(gtime.Now().Timestamp()),
			})
		}
	}
	// 设定团长积分
	if groupPoints > 0 {
		_, err = session.Where("id =?", headOrder.UserId).
			Incr("score", groupPoints).
			Update(&tables.User{})
		if err != nil {
			session.Rollback()
			return err
		}
		socre = append(socre, tables.UserScoreLog{
			Type:      "default",
			UserId:    headOrder.UserId,
			Score:     groupPoints,
			Remark:    "团长赠送积分",
			CreatedAt: gconv.Int(gtime.Now().Timestamp()),
		})
	}
	_, err = session.Table("user_score_log").InsertMulti(socre)
	if err != nil {
		session.Rollback()
		return err
	}
	if err = session.Commit(); err != nil {
		session.Rollback()
		return err
	}
	return nil
}
